package com.ittao.taoaicodeapp.core.handler;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ittao.taoaicodeai.ai.model.message.*;
import com.ittao.taoaicodeai.ai.tools.BaseTool;
import com.ittao.taoaicodeai.ai.tools.ToolManager;
import com.ittao.taoaicodeapp.service.ChatHistoryService;
import com.ittao.taoaicodemodel.model.entity.User;
import com.ittao.taoaicodemodel.model.enums.ChatHistoryMessageTypeEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.HashSet;
import java.util.Set;

/**
 * JSON 消息流处理器 - 简洁版
 * 处理 VUE_PROJECT 类型的复杂流式响应，包含工具调用信息
 * 提供简洁直观的工具调用可视化效果
 */
@Slf4j
@Component
public class JsonMessageStreamHandler {

    @Resource
    private ToolManager toolManager;

    /**
     * 处理 TokenStream（VUE_PROJECT）
     * 解析 JSON 消息并重组为完整的响应格式
     *
     * @param originFlux         原始流
     * @param chatHistoryService 聊天历史服务
     * @param appId              应用ID
     * @param loginUser          登录用户
     * @return 处理后的流
     */
    public Flux<String> handle(Flux<String> originFlux,
                               ChatHistoryService chatHistoryService,
                               long appId, User loginUser) {


        // 收集数据用于生成后端记忆格式
        StringBuilder chatHistoryStringBuilder = new StringBuilder();
        // 用于跟踪已经见过的工具ID，判断是否是第一次调用
        Set<String> seenToolIds = new HashSet<>();

        return originFlux
                .map(chunk -> {
                    // 解析每个 JSON 消息块
                    return handleJsonMessageChunk(chunk, chatHistoryStringBuilder, seenToolIds);
                })
                .filter(StrUtil::isNotEmpty) // 过滤空字串
                .doOnComplete(() -> {
                    // 流式响应完成后，添加 AI 消息到对话历史
                    String aiResponse = chatHistoryStringBuilder.toString();
                    chatHistoryService.addChatMessage(appId, aiResponse, ChatHistoryMessageTypeEnum.AI.getValue(), loginUser.getId());
                })
                .doOnError(error -> {
                    // 如果AI回复失败，也要记录错误消息，但只记录用户友好的错误信息
                    String errorMessage;
                    if ("InvalidRequestException".equals(error.getClass().getSimpleName())) {
                        // 处理 InvalidRequestException，检查是否为余额不足错误
                        String message = error.getMessage();
                        if (message != null && (message.contains("400 Bad Request") || 
                                               message.contains("Arrearage") || 
                                               message.contains("Access denied, please make sure your account is in good standing"))) {
                            errorMessage = "AI 服务余额不足，请联系管理员充值";
                        } else {
                            errorMessage = "AI 服务调用失败，请稍后重试";
                        }
                    } else {
                        errorMessage = "AI 生成代码失败，请稍后重试";
                    }
                    chatHistoryService.addChatMessage(appId, errorMessage, ChatHistoryMessageTypeEnum.AI.getValue(), loginUser.getId());
                });
    }

    /**
     * 解析并收集 TokenStream 数据
     */
    private String handleJsonMessageChunk(String chunk, StringBuilder chatHistoryStringBuilder, Set<String> seenToolIds) {
        // 解析 JSON
        StreamMessage streamMessage = JSONUtil.toBean(chunk, StreamMessage.class);
        StreamMessageTypeEnum typeEnum = StreamMessageTypeEnum.getEnumByValue(streamMessage.getType());

        switch (typeEnum) {
            case AI_RESPONSE -> {
                AiResponseMessage aiMessage = JSONUtil.toBean(chunk, AiResponseMessage.class);
                String data = aiMessage.getData();
                // 直接拼接响应返回给前端使用
                chatHistoryStringBuilder.append(data);
                return data;
            }
            case TOOL_REQUEST -> {
                ToolRequestMessage toolRequestMessage = JSONUtil.toBean(chunk, ToolRequestMessage.class);
                String toolId = toolRequestMessage.getId();
                String toolName = toolRequestMessage.getName();
                // 检查是否是第一次看到这个工具 ID
                if (toolId != null && !seenToolIds.contains(toolId)) {
                    // 第一次调用这个工具，记录 ID
                    seenToolIds.add(toolId);
                    // 根据工具名称获取工具实例
                    BaseTool tool = toolManager.getTool(toolName);
                    
                    // 检查是否为内部工具
                    if (tool.isInternalTool()) {
                        // 内部工具：不向前端返回任何信息
                        return "";
                    } else {
                        // 普通工具：返回格式化的工具调用信息
                        return tool.generateToolRequestResponse();
                    }
                } else {
                    // 不是第一次调用这个工具，直接返回空
                    return "";
                }
            }
            case TOOL_EXECUTED -> {
                ToolExecutedMessage toolExecutedMessage = JSONUtil.toBean(chunk, ToolExecutedMessage.class);
                JSONObject jsonObject = JSONUtil.parseObj(toolExecutedMessage.getArguments());
                String toolName = toolExecutedMessage.getName();
                // 根据工具名称获取工具实例
                BaseTool tool = toolManager.getTool(toolName);
                
                // 检查是否为内部工具
                if (tool.isInternalTool()) {
                    // 内部工具：完全静默执行，不记录历史，不返回前端
                    return ""; // 不向前端返回内容，也不记录到聊天历史
                } else {
                    // 普通工具：输出前端和要持久化的内容
                    String result = tool.generateToolExecutedResult(jsonObject);
                    chatHistoryStringBuilder.append(result);
                    return result;
                }
            }
            case null -> {
                log.error("未知的消息类型: {}", chunk);
                return "";
            }
            default -> {
                log.error("不支持的消息类型: {}", typeEnum);
                return "";
            }
        }
    }
}
